#ifndef RENDERTHREAD_H
#define RENDERTHREAD_H

#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <fstream>
#include <string>

#include "type.h"
#include "gemo.h"
#include "length_diff.h"

struct Parameter
{
    bool isExplicit;
    int MaxIte;
    int Jump;
    double TimeStep;
    double similarity;
    double VarVertex;
    double VarNormal;
};

class RenderThread : public QThread
{
    Q_OBJECT
public:
    QString ErrorCode;
    explicit RenderThread(QObject *parent = 0);
    bool runningState(){return !Stop;}
    void run();

    void setOutputFile(QString filename){outputFile = filename;}


    int Ite;
    int MaxIte;
    double TimeStep;
    double similarity;
    double VarVertex;
    double VarNormal;
    void setStart(bool state);
    void ClearData();
    bool hasData;
    bool isExplicit;
    bool OutputPerIter;

    std::ofstream log;
    std::vector<MPolygon> Polygons;
    std::vector<std::vector<int> > Joints;
    MPolygon iniPolygon;
signals:
   // void evolvePolygon(std::vector<MPolygon> &polygons);
    void evolvePolygon(MPolygon polygon, int k);
    void resetButton();

public slots:
    void getParameters(Parameter const *parameters,
                       MPolygon inipoly,
                       std::vector<MPolygon> & polygons,
                       int method);
    void threadReset();


private:
    QMutex mutex;
    QWaitCondition condition;
    bool Stop;
    bool isKeepShuffle;


    int method;
    int Jump;
    QString outputFile;

    std::vector<int> shuffle;
    std::vector<int> vTime;


    void OutputPolygon(std::vector<MPolygon> &polys, int num);
    void remesh(MPolygon *apoly, double criteria);
    bool arc_length(MPolygon const *inipoly, MPolygon *apoly, double similarity, double TimeStep);
    bool arc_length_sqrt(MPolygon const *inipoly, MPolygon *apoly, double similarity, double TimeStep);
    bool arc_length_four(MPolygon const *inipoly, MPolygon *apoly, double similarity, double TimeStep);

    bool local_area(MPolygon const *inipoly,
                           MPolygon *apoly,
                           double similarity, double TimeStep);
    bool local_area_abs(MPolygon const *inipoly,
                        MPolygon *apoly,
                        double similarity, double TimeStep);

    bool local_area_square(MPolygon const *inipoly,
                           MPolygon *apoly,
                           double similarity, double TimeStep);

    bool multiple_local_area(MPolygon const *inipoly,
                             MPolygon *apoly,
                             int jump, double similarity,
                             double TimeStep);

    bool cos_pi(MPolygon const *inipoly,
                MPolygon *apoly,
                double similarity,
                double TimeStep);

    bool turning_angle(MPolygon const *inipoly,
                       MPolygon *apoly,
                       double similarity,
                       double TimeStep);

    bool discrete_curvature_normal(MPolygon const *inipoly,
                                   MPolygon *apoly,
                                   double similarity,
                                   double TimeStep);

    bool bilateral_normal(MPolygon const *inipoly,
                          MPolygon *apoly,
                          double similarity,
                          double TimeStep,
                          double VarVertex,
                          double VarNormal);

    bool total_area(MPolygon const *inipoly,
                    std::vector<MPolygon> &polys,
                    double similarity, double TimeStep);

};

#endif // RENDERTHREAD_H
